package de.koller.worlders.render.visual;

import de.koller.oceanFramework.OceanException;
import de.koller.oceanFramework.gl.util.IRenderableImage;
import de.koller.oceanFramework.math.ROVec;
import de.koller.oceanFramework.util.ColorIntUtil;
import de.koller.worlders.engine.entity.AABBObject;
import de.koller.worlders.render.util.TextureRep;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;

public class DisplayRenderObject extends RenderObject {

	private int renderColor = 0xffffffff;
	private boolean mirrorX = false;
	private boolean mirrorY = false;
	private float rotation = 0;
	private float roX = 0;
	private float roY = 0;
	
	private static int number = 0;
	private boolean visible = true;
	protected float maxrange = 1+1+12*12+12*12;
	
	public DisplayRenderObject( int color ) {
		super( color );
		
		visible = ColorIntUtil.getAValue( color ) != 0;
		
		number++;
		if( number > 1000 )
			System.err.println( "Warning: More than 1000 objects!" );
	}

	public DisplayRenderObject( TextureRep texture ) {
		super( texture );
	}
	
	public void set( Object... val ) {

	}

	public void step( int elapsedTime ) {
		
	}
	
	public boolean isInRange( float x, float y ) {
		float dx = x - wroot.rendering.worlderV.getCameraMid().getXf();
		float dy = y - wroot.rendering.worlderV.getCameraMid().getYf();
		float r = dx*dx + dy*dy;
		return r < maxrange;
	}
	
	@Override
	public void renderObject( float x, float y, float w, float h, float z, boolean fast ) {
		renderObject( x, y, w, h, z, fast, 0, 0, 0, 1, 1, 1, 1, 0);
	}
	
	public void renderObject(	float x, float y, float w, float h, float z, boolean fast,
								float u0, float v0, float u1, float v1, float u2, float v2, 
								float u3, float v3 ) {
		if( !visible )
			return;
		if( !isInRange( x, y ) && wroot.rendering.worlderV.isCameraSet() )
			return;
		
		float uv0 = mirrorX ? u3 : u0;
		float vv0 = mirrorY ? v1 : v0;
		
		float uv1 = mirrorX ? u2 : u1;
		float vv1 = mirrorY ? v0 : v1;
		
		float uv2 = mirrorX ? u1 : u2;
		float vv2 = mirrorY ? v3 : v2;
		
		float uv3 = mirrorX ? u0 : u3;
		float vv3 = mirrorY ? v2 : v3;
		
		if( !fast ) {
			if( rotation != 0 ) {
				GL11.glPushMatrix();
				GL11.glTranslatef( x + roX, y + roY, 0 );
				GL11.glRotatef( rotation, 0, 0, 1 );
				GL11.glTranslatef( -x - roX, -y - roY, 0 );
			}
				
			getGenTexture();		
			preRendering();
			this.getTexture().draw2D( x, y, w, h, z, uv0, vv0, uv1, vv1, uv2, vv2, uv3, vv3 );
			
			if( rotation != 0 )
				GL11.glPopMatrix();
		} else
			this.getTexture().draw2DFast( x, y, w, h, z, uv0, vv0, uv1, vv1, uv2, vv2, uv3, vv3 );
		
		renderColor = 0xffffffff;
		mirrorX = false;
		mirrorY = false;
		rotation = 0;
		roX = 0;
		roY = 0;
	}

	/** v. Parameters definde the texturevisual */
	public static void renderAABB( AABBObject a, float depth ) {
		if( a.getVisual() == null )
			return;
		
		ROVec ro = a.getVisualRotationOffset();
		
		a.getVisual().setRotation( -a.getVisualRotation() );
		a.getVisual().setMirrorX( a.isMirrorX() );
		a.getVisual().setMirrorY( a.isMirrorY() );
		a.getVisual().setRotationOffsetX( ro.getXf() );
		a.getVisual().setRotationOffsetY( ro.getYf() );
		a.getVisual().setRenderColor( a.getTextureColor() );
		a.getVisual().renderObject( a.getVisualPos().getXf(), a.getVisualPos().getYf(), 
				a.getVisualSize().getXf(), a.getVisualSize().getYf(), depth, false );
	}
	
	public void preRendering() {
		GL11.glTexParameteri( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE );
		GL11.glTexParameteri( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE );
		
		preDROSet();
	}
	
	protected void preDROSet() {
		GL11.glColor3f( ColorIntUtil.getRValueF( renderColor ), 
						ColorIntUtil.getGValueF( renderColor ),
						ColorIntUtil.getBValueF( renderColor ) );
	}
	
	@Override
	public void setRenderColor( int renderColor ) {
		this.renderColor = renderColor;
	}
	
	public IRenderableImage getGenTexture() {
		if( this.getTexture() == null ) {
			if( this.getTextureRep() == null )
				throw new OceanException( "No Texture assigned" );
				//this.setTextureRep( new TextureRep( this.getColor() ) );
			
			this.setTexture( this.getTextureRep().generate( wroot.getBuffers() ) );
		}
		
		this.getTexture().bind();
		return this.getTexture();
	}

	@Override
	public boolean isVisible() {
		return visible;
	}

	public boolean isMirrorX() {
		return mirrorX;
	}

	public void setMirrorX( boolean mirrorX ) {
		this.mirrorX = mirrorX;
	}

	public boolean isMirrorY() {
		return mirrorY;
	}

	public void setMirrorY( boolean mirrorY ) {
		this.mirrorY = mirrorY;
	}

	public void setRotation( float rotation ) {
		this.rotation = rotation;
	}

	@Override
	public void setRotationOffsetX( float ox ) {
		this.roX = ox;
	}

	@Override
	public void setRotationOffsetY( float oy ) {
		this.roY = oy;
	}

	
}
